package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.OpenRouterApiClient;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.CustomerInfoMapper;
import com.ruoyi.system.mapper.FansInfoMapper;
import com.ruoyi.system.service.IFansInfoService;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import static com.ruoyi.common.utils.DeepLTranslationUtil.postMessage;

@Service
public class FansInfoServiceImpl implements IFansInfoService {
    private static final Logger log = LoggerFactory.getLogger(FansInfoServiceImpl.class);

    @Autowired
    private FansInfoMapper fansInfoMapper;

    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private CustomerInfoMapper waUserMapper;

    @Autowired
    private Environment env;

    @Autowired
    private WaURLService waURLService;

    @Autowired
    private RedisCache redisCache;


    private static List<CustomerInfo> cusCountlist = null;
    private static int currentIndex = 0;  // 当前处理的位置
    private final ReentrantLock lock = new ReentrantLock();

    private static int accumulatedClientCount = 0;  // 累积的 clientCount

    private static LocalDate currentDate = null;  // 当前日期

    private static boolean isResetNeeded = true;  //

    private static Map<String, Integer> dailyClientCountMap = new ConcurrentHashMap<>();

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    @Value("${devicesPath.clinetBluk}")
    private String clinetBluk;


    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<FansInfo> selectChatList(FansInfo customerChat) {
        List<FansInfo> userList = fansInfoMapper.selectChatList(customerChat);
//        userList.parallelStream().forEach(user -> {
////            Object objext = redisCache.getCacheObject(user.getClientNumber() + "-send_message");
////            if (StringUtils.isNotNull(objext)) {
////                String status = String.valueOf(objext);
////                user.setStatus(Integer.valueOf(status));
////                updateCustomerChat(user);
////            }
//
//            redisCache.setCacheObject(user.getClientNumber() + "-send_message",String.valueOf(user.getStatus()));
//        });

        return userList;
    }

    @Override
    public FansInfo selectChatByClientNumber(String selectChatByClientNumber) {
        return fansInfoMapper.selectChatByClientNumber(selectChatByClientNumber);
    }

    @Override
    public FansInfo selectChatById(String id) {
        return fansInfoMapper.selectChatById(id);
    }

    @Override
    public int updateCustomerChat(FansInfo customerChat) {
        redisCache.setCacheObject("persona:fans:" + customerChat.getClientNumber() + ":language", customerChat.getClientCountry());
        customerChat = getConfigKey(customerChat);
        return fansInfoMapper.updateCustomerChat(customerChat);
    }

    public FansInfo getConfigKey(FansInfo user) {
        CustomerInfo info = waUserMapper.selectUserByContactNumber(user.getCustomerNumber());
        try {
            ResponseEntity<String> jsonStr = OpenRouterApiClient.createApiKey(user.getClientNumber(), info.getConfigKey());
            // 解析JSON
            JSONObject json = JSON.parseObject(jsonStr.getBody());
            JSONObject data = json.getJSONObject("data");

            // 获取hash和label
            String hash = data.getString("hash");
            user.setKeyHash(hash);
            String label = json.getString("key");
            redisCache.setCacheObject("fans:apikey:" + user.getClientNumber(), label);
        } catch (Exception e) {
            log.error("insertUser:" + e);
        }
        return user;
    }

    /**
     * 新增客服信息
     *
     * @param user 客服信息
     * @return 结果
     */
    public int insertUser(FansInfo user) {
        user.setIsNew(1);
        CustomerInfo info = waUserMapper.selectUserByContactNumber(user.getCustomerNumber());
        Integer fansNumber = info.getFansNumber() + 1;
        info.setFansNumber(fansNumber);
        waUserMapper.updateFansNumber(info);
        redisCache.setCacheObject("persona:fans:" + user.getClientNumber() + ":language", user.getClientCountry());
        user = getConfigKey(user);
        return fansInfoMapper.insertUser(user);
    }


    @Override
    public int deleteUserByNumbers(String[] customerNumber) {
        for (String number : customerNumber) {
            CustomerInfo info = waUserMapper.selectByFansId(number);
            Integer fansNumber = info.getFansNumber() - 1;
            info.setFansNumber(fansNumber);
            waUserMapper.updateFansNumber(info);
            redisCache.deleteObject("fans:apikey:" + number);
        }

        return fansInfoMapper.deleteUserByNumbers(customerNumber);
    }


    @Override
    public String importUser(List<FansInfo> userList, Boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(userList) || userList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }

        AtomicInteger successNum = new AtomicInteger();
        AtomicInteger failureNum = new AtomicInteger();
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        resetAccumulatedClientCount();
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);

        // 假设 getCusUser() 是返回默认客服用户信息的方法，如果是这种情况，建议缓存它
//        CusUser defaultCusUser = getCusUser();

        // 通过 userList 获取所有非空的 customerNumber，进行批量查询
        Set<String> customerNumbers = userList.stream()
                .filter(user -> StringUtils.isNotEmpty(user.getCustomerNumber().trim()))
                .map(FansInfo::getCustomerNumber)
                .collect(Collectors.toSet());

        // 批量查询用户信息
//        Map<String, CusUser> cusUserMap = waUserMapper.selectUsersByNumbers(customerNumbers);

        Map<String, CustomerInfo> cusUserMap = waUserMapper.selectUsersByName(customerNumbers);

        // 批量查询现有的 chat 信息
        Set<String> clientNumbers = userList.stream()
                .map(user -> sendClientNumber(user.getClientNumber())) // {{ edit_1 }} 重新处理 getClientNumber
                .collect(Collectors.toSet());


        Map<String, FansInfo> existingChats = fansInfoMapper.selectChatsByClientNumbers(clientNumbers);

        // 使用 CountDownLatch 等待所有并行任务完成
        CountDownLatch latch = new CountDownLatch(userList.size());
        List<FansInfo> finalInsertList = Collections.synchronizedList(new ArrayList<>());
        Map<String, CustomerInfo> finalCusUserMap = cusUserMap;
        Map<String, FansInfo> finalExistingChats = existingChats;

        // 使用并行流处理用户列表，充分利用多核 CPU
        userList.parallelStream().forEach(user -> {
            try {
                CustomerInfo cusUser = null;

                // 如果没有 customerNumber，则使用默认客服账户
                if (StringUtils.isEmpty(user.getCustomerNumber())) {
                    cusUser = getCusUser();
                } else {
                    // 从缓存中获取对应的 CusUser 信息
                    cusUser = finalCusUserMap.get(user.getCustomerNumber().trim());
                }

                // 处理逻辑
                if (cusUser == null) {
                    failureNum.getAndIncrement();
                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getClientNumber() + " 没有找到对应的客服账户");
                    return;
                }
                FansInfo existingChat = finalExistingChats != null ? finalExistingChats.get(sendClientNumber(user.getClientNumber())) : null;

                if (existingChat == null) {
                    // 用户信息不存在，执行插入操作
                    user.setUserId(cusUser.getUserId());
                    user.setDeptId(cusUser.getDeptId());
                    user.setIsNew(1);
                    user.setStatus(0);
                    user.setClientName(DateUtils.dateTime());
                    String number = sendClientNumber(user.getClientNumber());

                    user.setClientNumber(number);
                    redisCache.setCacheObject(number + "-send_message", "0");
                    user.setCustomerNumber(cusUser.getContactName().trim());
                    user.setClientName(number);
                    user.setCreateTime(new Date());

                    // 线程安全的插入列表
                    synchronized (finalInsertList) {
                        finalInsertList.add(user);
                    }

                    successNum.getAndIncrement();
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getClientNumber() + " 导入成功");
                } else {
                    failureNum.getAndIncrement();
                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getClientNumber() + " 已存在");
                }

            } catch (Exception e) {
                failureNum.getAndIncrement();
                String msg = "<br/>" + failureNum + "、账号 " + user.getClientNumber() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            } finally {
                latch.countDown(); // 任务完成，减少计数
            }
        });

        // 等待所有任务完成
        try {
            latch.await();
        } catch (InterruptedException e) {
            log.error("导入任务等待中断", e);
            Thread.currentThread().interrupt();
        }

        // 批次提交优化
        if (!finalInsertList.isEmpty()) {
            try {
                fansInfoMapper.batchInsertUsers(finalInsertList);
                sqlSession.commit();
                finalInsertList.clear(); // 清空插入列表
            } catch (Exception e) {
                log.error("批量插入失败", e);
                throw new ServiceException("批量插入用户数据失败");
            }
        }

        // 返回处理结果
        if (failureNum.get() > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }


    public CustomerInfo getCusUser() {
        lock.lock();
        try {
            // 如果日期发生变化且标志位为true，重置累积值
            if (!LocalDate.now().equals(currentDate) && isResetNeeded) {
                resetAccumulatedClientCount();
                isResetNeeded = false;  // 设置为不再重置，直到下一天
            }
            // 循环遍历，直到找到一个符合条件的 CusUser
            while (currentIndex < cusCountlist.size()) {
                CustomerInfo chat = cusCountlist.get(currentIndex);

                // 获取当前 CusUser 的 clientCount
                int clientCount = 0;
                if (dailyClientCountMap.get(chat.getContactName()) == null) {
                    dailyClientCountMap.put(chat.getContactName(), 0);
                } else {
                    clientCount = dailyClientCountMap.get(chat.getContactName());
                    clientCount++;
                    dailyClientCountMap.put(chat.getContactName(), clientCount);
                }

                // 判断当前 CusUser 的 clientCount 是否可以加入累积值
                if (clientCount < 200) {
                    log.info("clientCount:" + clientCount);
                    // 如果累积值小于 500，则继续累加
                    return chat;  // 返回当前的 CusUser
                } else {
                    log.info("currentIndex:" + currentIndex);
                    currentIndex++;  // 跳到下一个 CusUser
                }
            }
        } finally {
            lock.unlock();
        }
        return null;
    }


    // 重置累积值和日期
    private void resetAccumulatedClientCount() {
        // 只在首次调用时或者日期发生变化时重置数据
        if (!LocalDate.now().equals(currentDate)) {
            currentDate = LocalDate.now();  // 当前日期
            List<CustomerInfo> list = waUserMapper.selectClientCount();
            cusCountlist = list;
            // 重置索引
            accumulatedClientCount = 0;
            currentIndex = 0;  // 重置索引
            isResetNeeded = true;  // 设置需要重置标志
            dailyClientCountMap = new ConcurrentHashMap<>();
        }
        currentIndex = 0;
    }

    public int updateCustomerByStatus(BulkSendName bulkSendName) {
        FansInfo fansInfo = new FansInfo();
        fansInfo.setCustomerNumber(bulkSendName.getOldContactNumber());
        fansInfo.setCustomerName(bulkSendName.getNewContactNumber());

        CustomerInfo user = waUserMapper.selectUserByContactName(bulkSendName.getNewContactNumber());
        if (StringUtils.isNull(user)) {
            throw new ServiceException(bulkSendName.getNewContactNumber() + "账户不存在");
        }

        return fansInfoMapper.updateCustomerByStatus(fansInfo);
    }

    @Override
    public int bulkMessage(BulkMessage bulkMessage) {
        try {
            List<FansInfo> list = fansInfoMapper.selectChatByIds(bulkMessage.getIds());
            for (FansInfo user : list) {
                String url = waURLService.getContactNumberURL(user.getCustomerNumber(), clinetBluk);
                postMessage(user.getCustomerNumber(), user.getClientNumber(), bulkMessage.getMessage(), bulkMessage.getTargetLanguage(), url, bulkMessage.getChatId());
            }
        } catch (Exception e) {
            return 0;
        }
        return 1;
    }

    private String sendClientNumber(String number) {
        number = number.trim();
        number = number.replace(" ", "");
        number = number.replace("+", "");
        if (number.startsWith("55")) {
            number = "+" + number;
        } else {
            number = "+55" + number;
        }
        return number;
    }

    @Override
    public void pauseChat(String[] id, int statics) {
        List<FansInfo> list = fansInfoMapper.selectChatByIds(id);
        list.stream().forEach(fansInfo -> {
            try {
                fansInfo.setStatus(statics);
                fansInfoMapper.updateCustomerByClientNumber(fansInfo);
                String keys = "persona:fans:" + fansInfo.getClientNumber() + ":statics";
                redisCache.setCacheObject(keys, String.valueOf(statics));
            } catch (Exception e) {
                log.error("tranChina:" + e);
            }
        });
    }

    @Override
    public List<ChatBoxInfo> getChatBoxList(String customerNumber) {
        List<ChatBoxInfo> list = fansInfoMapper.getChatBoxList(customerNumber);

        // 使用并行流处理未读消息数
        return list.parallelStream()
                .peek(info -> {
                    String key = "persona:fans:" + info.getId() + ":unread";
                    if (redisCache.hasKey(key)) {
                        info.setUnread(redisCache.getCacheObject(key));
                    }
                })
                .collect(Collectors.toList());
    }

    @Override
    public void updateManualService(String fansId, String status) {
        FansInfo fansInfo = fansInfoMapper.selectChatByClientNumber(fansId);
        fansInfo.setStatus(Integer.valueOf(status));
        fansInfoMapper.updateCustomerByClientNumber(fansInfo);
        String keys = "persona:fans:" + fansInfo.getClientNumber() + ":statics";
        redisCache.setCacheObject(keys, status);
    }

}
